<!DOCTYPE html>
<html lang="zh-cn">
  <head>
    <meta charset="UTF-8">
    <title>Sucha's Blog - Archive for June, 2019</title>
    <meta name="generator" content="MarkdownProjectCompositor.lua">
    <meta name="author" content="Sucha">
    <meta name="keywords" content="suchang, programming, Linux, Lua">
    <meta name="description" content="Sucha's blog">
    <link rel="shortcut icon" href="../images/ico.png">
    <link rel="stylesheet" type="text/css" href="../styles/blog.css">
    <link rel="stylesheet" type="text/css" href="../styles/prism.min.css">
    <style id="site_theme"></style>
  </head>
  <body>
    <div id="body">
      <div id="text">
	   <!-- Page published by cmark-gfm begins here --><h1>Sucha's Blog ~ Archive for June, 2019</h1>
<p><a id="p3"></a></p>
<div class="date">19年6月22日 周六 13:05</div>
<h2>更新 ThisSite 描述</h2>
<p><a href="../scratch/ThisSite.html">scratch#ThisSite</a> 写于网站搭建的第一天，蛮有纪念意义的，虽然 UI 未变，但换了 rendering 工具后，相关描述也得添加进去，当初围绕 Emacs 构建的一整套知识管理工具（因为当时 Emacs 确实好玩），现在慢慢的变成 IDE 不再重要了。</p>
<p>不过本站中，我最喜欢的页面，当然还是 <a href="../muse/haha.html">muse#haha</a>，-.-</p>
<div class="category"><a href="CategoryThisSite.html">CategoryThisSite</a> / <a href="2019-06.html#p3">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p2"></a></p>
<div class="date">19年6月15日 周六 13:18</div>
<h2>WelcomePage 的生成</h2>
<p>之前博客首页 WelcomePage 的生成，是在 proj 的 prepare 阶段，通过获取最新月份数据，动态产生内容，之后通过 body 函数提供给 <a href="https://github.com/github/cmark-gfm">cmark-gfm</a> 来生成最终的 html。</p>
<p>这里带来的问题是，对应的 Permalink 是不准确的，指向到首页去了。</p>
<p>为了解决这个问题，只好在全部内容生成之后，再搜集首页需要的数据；另外一种解决的办法，是用在语法上对首页的 Permalink 做特别处理，但这样太复杂了。</p>
<p>最后，是给 <a href="https://github.com/lalawue/MarkdownProjectCompositor">MarkdownProjectCompositor</a> 中每个 proj 处理完所有 files 后，增加一个 after 处理函数，可以在最后，对生成内容做采集。</p>
<p>这样，首页的 Permalink 指向才是准确的。</p>
<p>还有，现在用 <a href="https://github.com/jbt/markdown-editor">markdown-editor</a> 来写感觉很不错啊，<a href="../images/markdown_editor.jpg">有图为例</a>。</p>
<div class="category"><a href="CategoryProgramming.html">CategoryProgramming</a> / <a href="2019-06.html#p2">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p1"></a></p>
<div class="date">19年6月10日 周一 22:26</div>
<h2>MarkdownProjectCompositor</h2>
<p>这里介绍一下 <a href="https://github.com/lalawue/MarkdownProjectCompositor">MarkdownProjectCompositor</a> 对源文件的组织方式、处理流程，以及一些针对 Markdown 语法的扩展功能，最后说一下配置细节。</p>
<h3>源文件组织方式</h3>
<p>可以参考配置文件<sup><a href="#fnc1">1</a></sup>，定义了源文件目录、生成目录，同时定义了多个源文件子目录为 proj 工程目录，每个 proj 工程目录可以自定义不同 proj prepare 函数，每个源文件的 body 预处理函数、header 及 footer 样式。</p>
<p>这样可以有效处理主页源码、以及博客源码，处理各自不同的扩展语法，在 compostor 这一层，关注流程及数据传递，具体的扩展功能，是通过配置文件中复杂的功能函数来实现的。</p>
<p>在 proj 这一层，主要是获取子目录下的所有文件，交给 prepare 函数动态插入、删除文件，为接下来内容的动态生成做准备。</p>
<h3>处理流程</h3>
<p>每个 Markdown 文件的 rendering 过程，被分为 4 个阶段，分别是 body 预处理生成中间文件，输出 header、中间文件 rendering、输出 footer 后组成生成文件。</p>
<p><strong>1. body 源码预处理</strong></p>
<p>首先读取 Markdown 的源文件内容，将其作为参数传递给配置文件中某个 proj 定义的 body 函数做预处理，在这里用户可以处理自定义的标签，将其转为各种 Markdown rendering engine 支持的标准格式后，将内容交给 compositor 写入中间文件。</p>
<p><strong>2. header 生成文件头</strong></p>
<p>可以在这里区分不同的 proj，插入不同内容的文件头，比如主页的，博客的文件头，带上不同的样式表，同样支持动态生成内容。</p>
<p><strong>3. rendering 中间文件</strong></p>
<p>使用配置的 markdown rendering engine 处理这个中间文件，将生成内容添加到生成文件中。</p>
<p><strong>4. footer 生成文件尾</strong></p>
<p>这里类似 header 函数。</p>
<h3>语法扩展</h3>
<p>其实<a href="../blog/2019-06.html#p0">上篇博文</a>的最后有介绍，这里介绍语法，注意为了不被解析，用了 \</p>
<ul>
<li>支持工程间的引用</li>
</ul>
<pre><code class="language-source">[这篇文章]\(blog\#2019-06\#p1)
</code></pre>
<ul>
<li>生成文件内标题深度为 4 的目录摘要，例子是 <a href="../slack/SlackBook.html">Slackware Linux Essentials</a> 的本页目录</li>
</ul>
<pre><code class="language-source">#contents 4
</code></pre>
<ul>
<li>支持 footnote，看本文最后的配置文件标注</li>
</ul>
<pre><code class="language-source">这里有个标注[Desc]\(#fn1)
...
[Desc]\(#fn1)：解释这个标注
</code></pre>
<ul>
<li>博客 proj 里面良好的 HTML 标题结构、date、category 语法，这些是</li>
</ul>
<pre><code class="language-source"> #date 18年6月10日 周一 22:26
 #category Programming
</code></pre>
<ul>
<li>博客 proj 里动态生成 WelcomePage、Category 页面内容</li>
</ul>
<p>无法举例了，&gt;_&lt;</p>
<h3>配置、使用细节</h3>
<p>配置文件会使用 lua 的 dofile() 函数加载，返回类似的 table 就好，所以配置文件可以非常复杂，大大扩展 Markdown 语法。</p>
<p>使用方法如下，可选参数 PROJ_BASE_DIR，当 confg.lua 中的 source、build 配置为相对路径时可以使用，如果有跨平台写 Markdown 同学，应该需要这个吧。</p>
<pre><code class="language-sh">$ lua MarkdownProjectCompositor.lua config.lua [PROJ_BASE_DIR]
</code></pre>
<p>基本的配置下面有，注意 proj 中含有 res = true 的，意味着仅仅列举文件，但不做生成，用于上述扩展语法中做 proj 间的引用。</p>
<p>prepare 函数上面有介绍，当 proj 的 files 被填充后，会跑一次；body 用于生成临时源文件，自定义的语法在这里做转换，其他函数都有介绍过了。</p>
<p>最后的 user 不是必须的，但如果扩展了语法之类的，那可能就需要用到了，在 config 中带上，后面确保可以引用到。</p>
<p>最后的最后，当然是用生成当前主页、及博客的 <a href="https://github.com/lalawue/homepage/blob/master/misc/config.lua">config.lua</a> 来压轴。</p>
<p><sup>[<a id="fnc1">1</a>]</sup> config example:</p>
<pre><code class="language-lua">local config = {
   source = &quot;/Markdown/Source/Path&quot;, -- will be modified by compositor
   bulid = &quot;/Html/Output/Path&quot;,      -- will be modified by compositor
   suffix = &quot;.html&quot;,                 -- output suffix
   program = &quot;cmark-gfm&quot;,            -- program used
   params = &quot; -t html --unsafe --github-pre-lang &quot;,    -- params
   tmpfile = &quot;/tmp/MarkdownProjectCompositorTempFile&quot;, -- temp file
   projs = {
      {
         res = true,      -- resouces dir, when true do not build output
         dir = &quot;SourceSubPath&quot;,
         files = {
            -- file names filled by compositor
         },
         prepare = function( config, proj )
            -- prepare proj, sort/insert/delete proj files to be processed by cmark
         end,
         body = function( config, proj, filename, content )
            -- return modified source content before cmark process
         end,
         header = function( config, porj, filename )
            -- return content append in dest head
         end,
         footer = function( config, proj, filename )
            -- return content append in dest tail
         end,
      },
   },
   -- user defines below
   user = {
      readFile = function( path )
      end,
      writeFile = function( path, content )
      end,
      siteHeader = function( config, proj, filename )
      end,
      siteFooter = function( config, proj, filename )
      end,
   },
}
return config
</code></pre>
<div class="category"><a href="CategoryProgramming.html">CategoryProgramming</a> / <a href="2019-06.html#p1">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<p><a id="p0"></a></p>
<div class="date">19年6月9日 周日 23:59</div>
<h2>更换 Markdown Engine 为 cmark-gfm</h2>
<p>将本地 Markdown 渲染引擎换成了 <a href="https://github.com/github/cmark-gfm">cmark-gfm</a>，在这个基础上建立了类 EmacsWikiMode 的工程生成工具
<a href="https://github.com/lalawue/MarkdownProjectCompositor">MarkdownProjectCompositor</a>。</p>
<p>之前这个主页包括博客，是 2004 年底因为好奇 Wiki 语法而搭建起来的本地 HTML 文件，后来又学会了使用 FTP 上传免费的空间，绑定二级域名。</p>
<p>接着又学会了如何买域名，大学时代迷恋 Unix、Linux、Emacs 等等这一切对于普通人来说奇奇怪怪的东西，除了头脑发热在学校 BBS 上各种水文，
还在这里分门别类做了记录，慢慢的东西就多起来了。</p>
<p>这十多年间，不变的是，我得使用 Emacs 作为一个所见所得的编辑器，通过
<a href="https://github.com/lalawue/emacs-wiki-mode">EmacsWikiMode</a> 来写 Markdown，
为此自己在这个 mode 之上建立了 <a href="https://github.com/lalawue/emacs-wiki-journal">EmacsWikiJournal</a> 来专门写博客，基本上，
<a href="../scratch/EmacsWiki.html">这个过程还是很方便的</a>。</p>
<p>Markdown 最初的语法，都来自于 JOHN GRUBER 在 2004 年的
<a href="https://daringfireball.net/projects/markdown/syntax">Markdown: Syntax</a>。</p>
<p>因为 EmacsWikiMode 引用得早吧，所以在此之上，构建了很多独特的功能，比如自动生成目录摘要，比如将 Markdown 组织为各个工程，使用不同的配置文件头、
文件尾来生成 HTML，这样不同目录下的 HTML 可以使用不同的 CSS。而且，不同工程之间还可以很方便的引用。以及各种语法的高亮，将其输出为 HTML 文件。</p>
<p>也是蛮早，我就想着将博客的文件按照 YYYY-MM 这样组织，可以经受时间推移的考验，可是没想到，最大的不确定性，来自于 Emacs 的支持。</p>
<p>一方面，EmacsWikiMode 早就年久失修，maintainer 在 N 年以前，就构建了一个叫做 muse 的工程另起炉灶了。而 Emacs 社区本身，转到了 OrgMode 这一条路上
面，再说，其实一直都有 OutlineMode 可以用，也还勉勉强强。</p>
<p>加上外面各种 Markdown 桌面软件，网页端工具提供方便的界面，EmacsWikiMode 早就没有人用了，而我自己使用的频次也是越拉越少。</p>
<p>可悲的是，随着 Emacs 版本更新，大概在 version 24 的时候，EmacsWikiMode 在使用上就各种问题，version 25 之后，几乎无法生成了。</p>
<p>虽然是低频使用，但考虑到需要很长时间的支持，emacs-lisp 这种语言就得花费很多时间去维护，其作为 Emacs 环境编程工具，功能接口变动较大，
如果是 C 等等语言、库变动少的，基本上靠着 POSIX Like 的系统接口，维护成本可以很低。当然效率是另外一方面的加分吧。</p>
<p>所以，替换 Markdown 的 rendering engine，随着 Emacs 上 EmacsWikiMode 的可用性变得迫切起来，最终来了这次大改。</p>
<p>因为之前 EmacsWikiMode 功能丰富，加上自己对于 cmark 还不熟悉，所以功能上有取舍。另外之前为了在上面构建 EmacsWikiJournal，其实在 HTML 文件结构上
面，以及 Markdown 的语法上面，都有一些不妥的地方，这里一并修改过来了。</p>
<p>先说一些缺失的：</p>
<ul>
<li>不再支持生成 table 了，原来的 table 都是从 HTML 层面拷贝过来的</li>
<li>没有区分各种语言的语法高亮了<sup><a href="#fn1">1</a></sup></li>
<li>博客没有侧边栏的 calendar 了</li>
</ul>
<p>一些依旧支持，并做了改进的：</p>
<ul>
<li>支持工程间的引用</li>
<li>支持生成目录摘要</li>
<li>支持 footnote</li>
<li>博客里面良好的 HTML 标题结构、date、category 语法<sup><a href="#fn2">2</a></sup></li>
<li>动态生成 WelcomePage、Category 内容</li>
</ul>
<p><sup>[<a id="fn1">1</a>]</sup> <a href="../images/elisp_highlight_syntax.jpg">emacs-lisp 语法高亮图</a>
<sup>[<a id="fn2">2</a>]</sup> <a href="../images/md_cmark_syntax.jpg">新的博客结构</a></p>
<div class="category"><a href="CategoryThisSite.html">CategoryThisSite</a> / <a href="2019-06.html#p0">Permalink</a> / <a href="https://github.com/lalawue/homepage/discussions/categories/blog" target="_blank">Discussion</a></div>
<!-- Page published by cmark-gfm ends here -->
  <div id="foot">2004-<script>var d = new
	Date();document.write(d.getFullYear())</script> &copy;
	Sucha. Powered by MarkdownProjectCompositor.
  </div>
  </div><!-- text -->
  <div id="sidebar">
  </div><!-- sidebar -->
  <script src="../js/prism.min.js" async="async"></script>
  <script src="../js/blog_sidebar.js"></script>
  </div> <!-- body -->
</body>
</html>